package com.googlecode.perfectable.persistable.storage.memory;

import java.util.HashMap;
import java.util.Map;

import com.googlecode.perfectable.introspection.Bean;
import com.googlecode.perfectable.persistable.serialization.Separator;
import com.googlecode.perfectable.persistable.session.Identifier;
import com.googlecode.perfectable.persistable.session.InvalidReference;
import com.googlecode.perfectable.persistable.storage.AbstractStorage;
import com.googlecode.perfectable.persistable.storage.Persister;

public class MemoryStorage extends AbstractStorage {
	private final Map<Identifier<?>, Object> contents = new HashMap<>();
	private final Separator separator;
	private Persister relationPersister;

	public MemoryStorage(Separator separator) {
		this.separator = separator;
		this.relationPersister = this;
	}

	public MemoryStorage(Separator separator, Persister relationPersister) {
		this.separator = separator;
		this.relationPersister = relationPersister;
	}

	public void setRelationPersister(Persister relationPersister) {
		this.relationPersister = relationPersister;
	}

	@Override
	public <T> T materialize(Identifier<T> identifier) throws InvalidReference {
		T result = (T) this.contents.get(identifier);
		if(result == null) {
			throw new InvalidReference();
		}
		return result;
	}

	@Override
	public <T> void doPersist(T entity, Identifier<? super T> identity) {
		this.contents.put(identity, entity);
		for(Object related : Bean.from(entity).related()) {
			if(this.separator.isSeparate(related)) {
				this.relationPersister.persist(related);
			}
		}
	}

}
